<!--
@license
Copyright 2016 The TensorFlow Authors. All Rights Reserved.

Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at

    http://www.apache.org/licenses/LICENSE-2.0

Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
-->

<link rel="import" href="../iron-icon/iron-icon.html">
<link rel="import" href="../paper-input/paper-input.html">
<link rel="import" href="../polymer/polymer.html">
<link rel="import" href="../tf-backend/tf-backend.html">
<link rel="import" href="../tf-categorization-utils/tf-categorization-utils.html">
<link rel="import" href="../tf-categorization-utils/tf-category-pane.html">
<link rel="import" href="../tf-dashboard-common/dashboard-style.html">
<link rel="import" href="../tf-dashboard-common/tf-dashboard-layout.html">
<link rel="import" href="../tf-paginated-view/tf-paginated-view.html">
<link rel="import" href="../tf-runs-selector/tf-runs-selector.html">
<link rel="import" href="../tf-tensorboard/registry.html">
<link rel="import" href="tf-audio-loader.html">

<!--
tf-audio-dashboard displays a dashboard that loads audio from a TensorFlow run.
-->
<dom-module id="tf-audio-dashboard">
  <template>
    <tf-dashboard-layout>
      <div class="sidebar">
        <div class="sidebar-section">
          <tf-runs-selector
            id="runs-selector"
            selected-runs="{{_selectedRuns}}"
          ></tf-runs-selector>
        </div>
      </div>
      <div class="center">
        <template is="dom-if" if="[[_dataNotFound]]">
          <div class="no-data-warning">
            <h3>No audio data was found.</h3>
            <p>Probable causes:</p>
            <ul>
              <li>You haven’t written any audio data to your event files.
              <li>TensorBoard can’t find your event files.
            </ul>
            <p>
            If you’re new to using TensorBoard, and want to find out how
            to add data and set up your event files, check out the
            <a href="https://github.com/tensorflow/tensorboard/blob/master/README.md">README</a>
            and perhaps the <a href="https://www.tensorflow.org/get_started/summaries_and_tensorboard">TensorBoard tutorial</a>.
            <p>
            If you think TensorBoard is configured properly, please see
            <a href="https://github.com/tensorflow/tensorboard/blob/master/README.md#my-tensorboard-isnt-showing-any-data-whats-wrong">the section of the README devoted to missing data problems</a>
            and consider filing an issue on GitHub.
          </div>
        </template>
        <template is="dom-if" if="[[!_dataNotFound]]">
          <paper-input
            no-label-float
            label="Filter tags (regular expressions supported)"
            value="{{_tagFilter}}"
            class="search-input"
          >
            <iron-icon prefix icon="search"></iron-icon>
          </paper-input>
          <template is="dom-repeat" items="[[_categories]]" as="category">
            <tf-category-pane category="[[category]]" opened="[[_shouldOpen(index)]]">
              <tf-paginated-view
                items="[[category.items]]"
                pages="{{category._pages}}"
              >
                <template is="dom-repeat" items="[[category._pages]]" as="page">
                  <template is="dom-if" if="[[page.active]]">
                    <div class="layout horizontal wrap">
                      <template is="dom-repeat" items="[[page.items]]">
                        <tf-audio-loader
                          run="[[item.run]]"
                          tag="[[item.tag]]"
                          sample="[[item.sample]]"
                          total-samples="[[item.totalSamples]]"
                          tag-metadata="[[_tagMetadata(_runToTagInfo, item.run, item.tag)]]"
                          request-manager="[[_requestManager]]"
                        ></tf-audio-loader>
                    </div>
                  </template>
                </template>
              </tf-paginated-view>
            </tf-category-pane>
          </template>
        </template>
      </div>
    </tf-dashboard-layout>
    <style include="dashboard-style"></style>
    <style>
      .no-data-warning {
        max-width: 540px;
        margin: 80px auto 0 auto;
      }
    </style>
  </template>
  <script>
    "use strict";


    Polymer({
      is: 'tf-audio-dashboard',
      properties: {
        _selectedRuns: Array,
        _runToTagInfo: Object,
        _dataNotFound: Boolean,

        _tagFilter: {
          type: String,  // upward bound from paper-input
          value: '',
        },
        _categories: {
          type: Array,
          computed:
            '_makeCategories(_runToTagInfo, _selectedRuns, _tagFilter)',
        },

        _requestManager: {
          type: Object,
          value: () => new tf_backend.RequestManager(),
        },
      },

      ready() {
        this.reload();
      },
      reload() {
        this._fetchTags().then(() => {
          this._reloadAudio();
        });
      },
      _fetchTags() {
        const url = tf_backend.getRouter().pluginRoute('audio', '/tags');
        return this._requestManager.request(url).then(runToTagInfo => {
          if (_.isEqual(runToTagInfo, this._runToTagInfo)) {
            // No need to update anything if there are no changes.
            return;
          }
          const runToTag = _.mapValues(runToTagInfo, x => Object.keys(x));
          const tags = tf_backend.getTags(runToTag);
          this.set('_dataNotFound', tags.length === 0);
          this.set('_runToTagInfo', runToTagInfo);
        });
      },
      _reloadAudio() {
        this.querySelectorAll('tf-audio-loader').forEach(audio => {
          audio.reload();
        });
      },

      _shouldOpen(index) {
        return index <= 2;
      },

      _makeCategories(runToTagInfo, selectedRuns, tagFilter) {
        const runToTag = _.mapValues(runToTagInfo, x => Object.keys(x));
        const baseCategories =
          tf_categorization_utils.categorizeRunTagCombinations(runToTag, selectedRuns, tagFilter);
        function explodeItem(item) {
          const samples = runToTagInfo[item.run][item.tag].samples;
          return _.range(samples).map(i => Object.assign({}, item, {
            sample: i,
            totalSamples: samples,
          }));
        }
        const withSamples = baseCategories.map(category =>
          Object.assign({}, category, {
            items: [].concat.apply([], category.items.map(explodeItem)),
          }));
        return withSamples;
      },
      _tagMetadata(runToTagInfo, run, tag) {
        return runToTagInfo[run][tag];
      },
    });

    tf_tensorboard.registerDashboard({
      plugin: 'audio',
      elementName: 'tf-audio-dashboard',
    });

  </script>
</dom-module>
